import React from "react";
import { Router, Route, Switch } from "dva/router";
import { LocaleProvider, Spin } from "antd";
import axios from "axios";
import zhCN from "antd/lib/locale-provider/zh_CN";
import dynamic from "dva/dynamic";
import cloneDeep from "lodash/cloneDeep";
import { getNavData } from "./common/nav";
import { getPlainNode } from "./utils/utils";

import styles from "./index.less";

const pending = []; //声明一个数组用于存储每个ajax请求的取消函数和ajax标识
const { CancelToken } = axios;
const removePending = config => {
  for (const p in pending) {
    if (pending[p].u === config.url + "&" + config.method) {
      //当当前请求在数组中存在时执行函数体
      pending[p].f(); //执行取消操作
      pending.splice(p, 1); //把这条记录从数组中移除
    }
  }
};

dynamic.setDefaultLoadingComponent(() => {
  return <Spin size="large" className={styles.globalSpin} />;
});

class Loading extends React.Component {
  state = { loading: false };
  componentDidMount() {
    axios.interceptors.request.use(
      config => {
        removePending(config); //在一个ajax发送前执行一下取消操作
        config.cancelToken = new CancelToken(c => {
          // 这里的ajax标识我是用请求地址&请求方式拼接的字符串，当然你可以选择其他的一些方式
          pending.push({
            u: config.url + "&" + config.method + config.data,
            f: c
          });
        });

        this.setState({ loading: true });
        return config;
      },
      err => {
        this.closeLoading();
        return Promise.reject(err);
      }
    );

    axios.interceptors.response.use(
      res => {
        removePending(res.config);
        this.closeLoading();
        return res;
      },
      err => {
        this.closeLoading();
        return Promise.reject(err);
      }
    );
  }

  closeLoading = () => {
    setTimeout(() => {
      this.setState({ loading: false });
    });
  };
  render() {
    return (
      <Spin
        wrapperClassName="wrapperClassName-spin"
        spinning={this.state.loading}
      >
        {this.props.children}
      </Spin>
    );
  }
}

function getRouteData(navData, path) {
  if (
    !navData.some(item => item.layout === path) ||
    !navData.filter(item => item.layout === path)[0].children
  ) {
    return null;
  }
  const route = cloneDeep(navData.filter(item => item.layout === path)[0]);
  const nodeList = getPlainNode(route.children);
  return nodeList;
}

function getLayout(navData, path) {
  if (
    !navData.some(item => item.layout === path) ||
    !navData.filter(item => item.layout === path)[0].children
  ) {
    return null;
  }
  const route = navData.filter(item => item.layout === path)[0];
  return {
    component: route.component,
    layout: route.layout,
    name: route.name,
    path: route.path
  };
}

function RouterConfig({ history, app }) {
  const navData = getNavData(app);
  const UserLayout = getLayout(navData, "UserLayout").component;
  const BasicLayout = getLayout(navData, "BasicLayout").component;

  const passProps = {
    app,
    navData,
    getRouteData: path => {
      return getRouteData(navData, path);
    }
  };

  return (
    <LocaleProvider locale={zhCN}>
      <Loading>
        <Router history={history}>
          <Switch>
            <Route
              path="/user"
              render={props => <UserLayout {...props} {...passProps} />}
            />
            <Route
              path="/"
              render={props => <BasicLayout {...props} {...passProps} />}
            />
          </Switch>
        </Router>
      </Loading>
    </LocaleProvider>
  );
}

export default RouterConfig;
